#include "klib.h"

#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)

size_t strlen(const char *s) {
  // printf("entering strlen\n");
  assert(s);
  const char *temp = s;
  int count = 0;
  if (temp==NULL || *temp=='\0') return 0;
  while (*temp!='\0') {
    temp++;
    count++;
  }
  return count;
}

char *strcpy(char* dst,const char* src) {
  // printf("entering strcpy\n");
  assert(dst && src);
  char* addr = dst;
  while (*src != '\0') {
    *dst = *src;
    dst++;
    src++;
  }
  assert(*src=='\0');
  *dst = '\0';

  return addr;
}

char* strncpy(char* dst, const char* src, size_t n) {
  // printf("entering strncpy\n");
  assert(dst && src);
  char* addr = dst;
  size_t count = 0;
  while (*src!='\0' && count < n) {
    *dst = *src;
    dst++;
    src++;
    count++;
  }
  assert(*src=='\0');
  *dst = '\0';

  return addr;
}

char* strcat(char* dst, const char* src) {
  // printf("entering strcat\n");
  char* addr = dst;
  assert(dst && src);
  while (*dst!='\0') {
    dst++;
  }
  assert(*dst=='\0');

  while (*src!='\0') {
    *dst = *src;
    dst++;
    src++;
  }
  assert(*src=='\0');
  *dst = '\0';
  return addr;
}

int strcmp(const char* s1, const char* s2) {
  // printf("entering strcmp\n");
  
  if (s1==NULL) return 0-*s2;
  else if (s2==NULL) return *s1-0;
  while(!(*(unsigned char*)s1-*(unsigned char*)s2) && *s1!='\0' && *s2!='\0') {
    s1++;
    s2++;
  }
  return  *s1 - *s2;
}

int strncmp(const char* s1, const char* s2, size_t n) {
  // printf("entering strncmp\n");
  assert(s1 && s2);
  int compared = 0;
  while (!(*(unsigned char*)s1-*(unsigned char*)s2) && *s1!='\0' && *s2!='\0' && compared<n) {
    s1++;
    s2++;
    compared++;
  }
  return *s1-*s2;
}

void* memset(void* v,int c,size_t n) {
  // printf("entering memset\n");
  if (v==NULL) return v;
  assert(v && n>=0);
  char* temp = (char*) v;
  while(n>0) {
    *temp = c;
    temp++;
    n--;
  }

  return v;
}

void* memcpy(void* out, const void* in, size_t n) {
  // printf("entering memcpy\n");
  // if (out==NULL) printf("out is NULL\n");
  // if (in==NULL) printf("in is NULL\n");
  // if (n<0) printf("n is less than 0\n");
  if (out==NULL) return out;
  assert(out && in && n>=0);
  char* temp_out = (char*) out;
  char* temp_in = (char*) in;
  while (n>0) {
    *temp_out = *temp_in;
    temp_out++;
    temp_in++;
    n--;
  }
  
  return out;
}

int memcmp(const void* s1, const void* s2, size_t n){
  // printf("entering memcmp\n");
  assert(s1 && s2 && n>=0);
  char* temp1 = (char*) s1;
  char* temp2 = (char*) s2;
  while(!(*temp1-*temp2) && n>1) {
    temp1++;
    temp2++;
    n--;
  }
  return *temp1-*temp2;
}

#endif
